Ext.ns("org.cancerregulome.view");

org.cancerregulome.view.ColumnHelper = Ext.extend(Object, {
    linkColumns: [],
    imageColumns: [],
    columnSpecs: {},

    constructor: function(spec) {
        if (spec.columnSpecs) this.columnSpecs = spec.columnSpecs;
        for (var key in this.columnSpecs) {
            if (this.columnSpecs.hasOwnProperty(key)) {
                var colSpec = this.columnSpecs[key];
                if (colSpec.isImage) {
                    this.imageColumns.push(key);
                } else if (colSpec.isLink) {
                    this.linkColumns.push(key);
                }
            }
        }

        Ext.each(this.columnSpecs, function(colSpec) {
            if (colSpec.isImage) this.imageColumns.push(colSpec);
        }, this);
    },

    isLinkColumn: function(column) {
        return (this.linkColumns.length && (this.linkColumns.indexOf(column) >= 0));
    },

    isImageColumn: function(column) {
        return (this.imageColumns.length && (this.imageColumns.indexOf(column) >= 0));
    },

    isHidden: function(column) {
        var colspec = this.columnSpecs[column];
        return colspec && colspec.hidden;
    },

    getColumnWidth: function(column) {
        var colspec = this.columnSpecs[column];
        if (colspec && colspec.width) {
            return colspec.width;
        }
        return 100;
    },

    getColumnDataType: function(column) {
        var colspec = this.columnSpecs[column];
        if (colspec && colspec.type) {
            return colspec.type;
        }
        return "auto";
    },

    isSortable: function(column) {
        return !this.isLinkColumn(column);
    },

    getValue: function(fieldname, cell) {
        if (this.isLinkColumn(fieldname)) {
            return this.getLinksCell(cell);
        }
        return cell;
    },

    getLinksCell: function(cell) {
        if (cell && cell != "NA") {
            return '<a href="' + cell + '" target="_blank">' + cell + '</a>';
        }
        return cell;
    },

    orderFields: function(items, fields) {
        var orderedItems = [];
        var unorderedItems = [];

        Ext.each(items, function(item) {
            var colspec = this.columnSpecs[item.originalKey];
            if (colspec && colspec.order != null) {
                orderedItems[colspec.order] = item;
            } else {
                unorderedItems.push(item);
            }
        }, this);

        var appendFn = function(item) { fields.push(item); };
        Ext.each(orderedItems, appendFn);
        Ext.each(unorderedItems, appendFn);
    }
});

org.cancerregulome.view.TsvDecode = function(responseText) {
    var lines = responseText.split("\n");
    var firstLine = lines[0].split("\t");
    var i = 0;

    var resultArray = [];
    Ext.each(lines, function(line) {
        if (i++ > 0) {
            var item = {};
            var values = line.split("\t");
            if (values.length == firstLine.length) {
                for (var j = 0; j < values.length; j++) {
                    item[firstLine[j]] = values[j];
                }
                resultArray.push(item);
            }
        }
    });
    return resultArray;
};

org.cancerregulome.view.AnnotationsGrid = Ext.extend(Ext.util.Observable, {

    constructor: function(uri, config, agconfig) {
        this.uri = uri;
        this.columnHelper = new org.cancerregulome.view.ColumnHelper(config);
        this.agconfig = agconfig ? agconfig : {};
        this.downloadUrl = this.uri + "/annotations.tsv";
        this.archiveUrl = this.uri + "/files.zip";

        this.addEvents("select-item", "grid-ready");

        org.cancerregulome.view.AnnotationsGrid.superclass.constructor.call(this);

        Ext.Ajax.request({
            url: this.uri + "/annotations.tsv",
            method: "GET",
            success: this.load,
            scope: this
        });
    },

    load: function(response) {
        var fields = [];
        var data = [];

        var jsonArray = org.cancerregulome.view.TsvDecode(response.responseText);
        if (jsonArray && jsonArray.length) {
            this.setColumnHeaders(jsonArray[0], fields);
            Ext.each(jsonArray, function(item) {
                this.addRow(item, fields, data);
            }, this);
        }

        var filterFields = [];
        Ext.each(fields, function(field) {
            if (field.type == "float" || field.type == "int") {
                filterFields.push({type:"numeric", dataIndex:field.dataIndex});
            } else {
                filterFields.push({type:"string", dataIndex:field.dataIndex});
            }
        });

        this.store = new Ext.data.ArrayStore({ fields: fields, data: data, id: Ext.id() });

        var gridConfig = Ext.apply({
            store: this.store,
            colModel: new Ext.grid.ColumnModel({
                defaults: { width: 200, sortable: true }, columns: fields
            }),
            iconCls: 'icon-grid',
            stripeRows: true,
            columnLines: true,
            frame:true,
            collapsible: false,
            animCollapse: false,
            plugins: [ new Ext.ux.grid.GridFilters({ encode: false, local: true, filters: filterFields }) ],
            tbar: [
                { text: "Datasets", menu: new org.cancerregulome.view.DatasetsMenu(this.uri) },
                "-",
                {
                    text: "Download Table",
                    handler: function() {
                        document.location = this.downloadUrl;
                    },
                    scope: this
                }
//                ,
//                "-"
//                ,
//                {
//                    text: "Download Files (zip)",
//                    handler: function() {
//                        document.location = this.archiveUrl;
//                    },
//                    scope: this
//                }
            ],
            listeners: {
                scope: this,
                "cellclick": function(g, rowIndex, columnIndex) {
                    var record = g.getStore().getAt(rowIndex);
                    var fieldName = g.getColumnModel().getDataIndex(columnIndex);
                    var column = g.getColumnModel().getColumnById(fieldName);
                    var selectItem = { id: "row_" + rowIndex, record: record, label: record.json[0] }
                    if (this.columnHelper.isImageColumn(column.header)) {
                        selectItem.selectedFieldId = fieldName;
                    }
                    this.fireEvent("select-item", selectItem);
                }
            }
        }, this.agconfig);

        this.gridPanel = new Ext.grid.GridPanel(gridConfig);

        this.fireEvent("grid-ready");
    },

    setColumnHeaders: function(firstItem, fields) {
        var items = [];
        for (var key in firstItem) {
            if (firstItem.hasOwnProperty(key)) {
                var headerId = Ext.id();
                items[items.length] = {
                    id: headerId,
                    name: headerId,
                    dataIndex: headerId,
                    originalKey: key,
                    header: key.trim(),
                    type: this.columnHelper.getColumnDataType(key),
                    isImage: this.columnHelper.isImageColumn(key),
                    hidden: this.columnHelper.isHidden(key),
                    sortable: this.columnHelper.isSortable(key),
                    width: this.columnHelper.getColumnWidth(key)
                };
            }
        }

        this.columnHelper.orderFields(items, fields);
    },

    addRow: function(item, fields, data) {
        var rowData = [];
        Ext.each(fields, function(f) {
            rowData[rowData.length] = this.columnHelper.getValue(f.originalKey, item[f.originalKey]);
        }, this);
        data[data.length] = rowData;
    }
});

org.cancerregulome.view.AnnotationsDetailPanel = Ext.extend(Object, {

    constructor: function(uri, config) {
        this.uri = uri;
        this.tabPanel = new Ext.TabPanel(Ext.apply({
            enableTabScroll: true,
            margins: "5 5 5 5",
            activeTab: 0,
            height: 400,
            items:[]
        }, config));
    },

    show: function(item) {
        var record = item.record;

        var data = [];
        Ext.each(record.fields.items, function(fieldItem) {
            data.push([fieldItem.header, record.get(fieldItem.id)]);
        });

        var detailView = new Ext.DataView({
            title: "Details",
            region: "east",
            width: 500,
            height: 400,
            margins: "5 5 5 5",
            store: new Ext.data.ArrayStore({ fields: ['label', 'value'], data : data }),
            tpl: new Ext.XTemplate(
                '<table class="table_details">',
                '<tpl for=".">',
                '<tr><td><b>{label}</b></td><td>{value}</td></tr>',
                '</tpl>',
                '</table>'
            )
        });

        var tabId = "tab_" + item.id;
        var newtab = new Ext.Panel({
            id: tabId,
            title: item.label,
            layout: "border",
            closable: true,
            autoScroll: true,
            items: [ detailView, this.getImagePanel(item, record) ]
        });

        var existingTab = this.tabPanel.getTabEl(tabId);
        if (existingTab != null) {
            var tabIdx = 0;
            var tabitems = this.tabPanel.items.items;
            for (var i = 0; i < tabitems.length; i++) {
                var tabitem = tabitems[i];
                if (tabitem.id == tabId) {
                    tabIdx = i;
                }
            }
            this.tabPanel.remove(tabId);
            this.tabPanel.insert(tabIdx, newtab);
        } else {
            this.tabPanel.add(newtab);
        }

        this.tabPanel.setActiveTab(tabId);
    },

    getImagePanel: function(item, record) {
        if (item.selectedFieldId) {
            var alt = record.get(item.selectedFieldId);
            var src = this.uri + "/" + alt;

            var dataview = new Ext.DataView({
                style:'overflow:auto',
                store: new Ext.data.ArrayStore({ fields: ['alt', 'src'], data : [[alt, src]] }),
                tpl: new Ext.XTemplate('<tpl for="."><img id="{id}" alt="{alt}" src="{src}"/></tpl>')
            });

            return new Ext.Panel({ region:'center', layout:'fit', items: [ dataview ] });
        }
        return { region: "center", html: "No Image Selected" };
    }

});

org.cancerregulome.view.DatasetsMenu = Ext.extend(Ext.menu.Menu, {

    constructor: function(uri) {
        var lastSlash = uri.lastIndexOf("/");
        if (lastSlash == uri.length) lastSlash--;

        org.cancerregulome.view.DatasetsMenu.superclass.constructor.call(this);

        var locHref = document.location.href;
        var linkUrl = locHref.substring(0, locHref.length - document.location.search.length)
        Ext.Ajax.request({
            url: uri.substring(0, lastSlash),
            method: "GET",
            success: function(o) {
                var json = Ext.util.JSON.decode(o.responseText);
                if (json && json.items) {
                    Ext.each(json.items, function(item) {
                        this.add(new Ext.Action({
                            text: item.label,
                            handler: function() {
                                document.location = linkUrl + "?uri=" + item.uri;
                            }
                        }));
                    }, this);
                }
            },
            scope: this
        });
    }

});
